package com.black.service.service;

import com.alibaba.fastjson2.JSONObject;
import com.black.protocol.ErrorCode;
import com.black.protocol.Response;
import com.black.service.dao.ResourceDao;
import com.black.service.entity.ResourceEntity;
import com.black.utils.encrypt.sm4.SM4Util;
import com.black.utils.file.FileTypeEnum;
import com.black.utils.file.FileUtil;
import com.black.utils.file.image.code.QRCodeUtil;
import com.black.utils.token.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;

@Slf4j
@Service
public class ResourceServiceImpl implements ResourceService {
    @Resource
    private ResourceDao resourceDao;

    @Value("${tmp.file.location}")
    private String fileLocation;

    private static final String IMAGE_SUB_PATH = "image";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<?> saveFile(ResourceEntity resourceEntity) {
        byte[] resourceData = resourceEntity.getResourceData();
        if (resourceData == null || resourceData.length == 0) {
            return Response.fail(ErrorCode.ERROR_PARAM_MISSING);
        }
        String filename = resourceEntity.getResourceName() + FileTypeEnum.getSuffix(resourceEntity.getResourceType());
        String filePath = FileUtil.buildPath(fileLocation, IMAGE_SUB_PATH);
        boolean isSuccess = FileUtil.saveBytes(filePath, filename, resourceData);
        if (!isSuccess) {
            return Response.fail(ErrorCode.ERROR_FILE_SAVE_FAILED);
        }
        resourceEntity.setResourceUrl(IMAGE_SUB_PATH + FileTypeEnum.PATH_SEPARATOR + filename);
        if (resourceEntity.getCreateTime() == null) {
            resourceDao.insert(resourceEntity);
        } else {
            resourceDao.updateById(resourceEntity);
        }
        return Response.success(resourceEntity);
    }

    @Override
    public byte[] loadFile(String resourceId) {
        String subPath = getUrlByResourceId(resourceId);
        if (subPath == null) {
            return null;
        }
        try
        {
            return FileUtil.loadFile(fileLocation + FileTypeEnum.PATH_SEPARATOR + subPath);
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getUrlByResourceId(String resourceId) {
        ResourceEntity resourceEntity = resourceDao.selectById(resourceId);
        return resourceEntity == null ? null : resourceEntity.getResourceUrl();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<?> generateQrCode(JSONObject params) {
        String content = params.getString("content");
        String resourceId = SM4Util.encryptData_CBC(content);
        boolean writeText = params.getBooleanValue("writeText");
        ResourceEntity resourceEntity = resourceDao.selectById(resourceId);
        if (resourceEntity == null) {
            resourceEntity = new ResourceEntity();
        }
        Integer width = params.getInteger("width");
        if (content == null || content.isEmpty()) {
            return Response.fail(ErrorCode.ERROR_PARAM_ILLEGAL);
        }
        byte[] bytes = null;
        try {
            if (width == null || width < 0) {
                bytes = QRCodeUtil.createQrCode(content, writeText);
            } else {
                bytes = QRCodeUtil.createQrCode(content, width, writeText);
            }
        } catch (Exception e) {
            log.error("生成二维码失败", e);
            return Response.fail(ErrorCode.ERROR_UNKNOWN);
        }
        resourceEntity.setResourceId(resourceId);
        resourceEntity.setResourceType(FileTypeEnum.PNG.getExtension());
        String resourceName = TokenUtil.makeToken(content).replaceAll("/", "");
        resourceName = resourceName.replaceAll("\\\\", "");
        resourceEntity.setResourceName(resourceName);
        resourceEntity.setResourceData(bytes);
        return saveFile(resourceEntity);
    }
}
